package com.sprouting.ops.annotations.service;

import com.sprouting.ops.annotations.invoke.CheckLength;
import com.sprouting.ops.interfaces.ConstantBase;
import lombok.extern.slf4j.Slf4j;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.io.UnsupportedEncodingException;

/**
 * CheckLength 注解验证实现
 * 注意，该注解验证的是字符串的长度，所有这里的目标是 String，使用的编码是 utf-8
 *
 * @author ：LX（长沙麓谷）
 * @date 创建时间： 2023/3/10 18:00
 */
@Slf4j
public class CheckLengthValidator implements ConstraintValidator<CheckLength, String> {

    /**
     * 默认的字段长度
     */
    private int min = 0;
    private int max = Integer.MAX_VALUE;
    private String computeMode = "byte";
    private boolean isJoin = true;
    /**
     * 提示信息
     */
    private String message;


    /**
     * 常量-字符计算模式
     */
    private final String STRING = "string";

    /**
     * 初始化方法
     * 只会调用一次，将注解中的数据放入到这个类成员变量中，故而不要在这里去改动成员变量的数据，否则会导致数据变化。要使用请直接复制一份，否则会改变原来的值
     * @param constraintAnnotation 注解
     */
    @Override
    public void initialize(CheckLength constraintAnnotation) {
        this.min = constraintAnnotation.min();
        this.max = constraintAnnotation.max();
        this.computeMode = constraintAnnotation.computeMode();
        this.isJoin = constraintAnnotation.isJoin();
        this.message = constraintAnnotation.message();
    }

    /**
     * 校验方法
     * @param value 需要验证的值
     * @param context 校验的上下文
     * @return true 校验成功， false 不合法
     */
    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        if (value == null || "".equals(value)){
            return true;
        }

        if (min < 0) {
            min = 0;
        }

        // 计算出的长度
        int vl;
        if (STRING.equals(computeMode)){
            // 按照字符计算
            vl = value.length();
        } else {
            // 默认按照字节计算
            try {
                //转换为数据库的长度
                vl = value.getBytes(ConstantBase.Encoded.UTF).length;
            } catch (UnsupportedEncodingException e) {
                log.error("校验数据长度发生异常", e);
                return false;
            }
        }

        if (min <= vl && vl <= max){
            return true;
        }

        // 是否改写错误返回信息
        if (isJoin){
            // 禁用默认的错误提示
            context.disableDefaultConstraintViolation();
            StringBuilder msg = new StringBuilder();
            if (message.length() > 0){
                msg.append(message).append(",");
            }

            if (STRING.equals(computeMode)){
                msg.append(String.format("可输入[%s ~ %s]个字符，已输入[%s]个字符", min, max, vl));
            } else {
                msg.append(String.format("可输入[%s ~ %s]个字节，已输入[%s]个字节", min, max, vl));
            }
            // 添加自定义错误提示信息
            context.buildConstraintViolationWithTemplate(msg.toString()).addConstraintViolation();
        }

        return false;
    }
}
